import {HttpStatus} from "~/types/enums";
import {baseUrl} from "~/utils/config";
import {getToken, removeToken, removeUserInfo} from "~/utils/cookie";
import {encryptBase64, encryptWithAes, generateAesKey} from "~/utils/crypto";
import CryptoJS from "crypto-js";
import {inBrowser} from "~/utils/nuxt/constants";
// 客户端时，引入
let apiEncrypt: any;
if (inBrowser) {
    import('~~/utils/jsencrypt').then((res) => {
        apiEncrypt = res.apiEncrypt
    })
}

/**
 * 说明：isNeedToken：是否为请求头添加Authorizationq
 * isEncrypt：是否加密数据，只对post和put接口加密数据
 */
const errorCode: Record<string, string> = {
    "401": "请先登录哦~~",
    "403": "当前操作没有权限，请联系管理员吧~",
    "404": "访问资源不存在",
    default: "系统未知错误，请反馈给管理员吧~",
};

const aesKey: CryptoJS.lib.WordArray = generateAesKey();

const requestHeaders = (needToken: boolean, isEncrypt: boolean) => {
    const headers: Record<string, string> = {};
    if (needToken && getToken()) {
        headers.Authorization = `Bearer ${getToken()}`;
    }
    if (isEncrypt) {
        // 生成一个 AES 密钥
        headers['Encrypt-Key'] = apiEncrypt(encryptBase64(aesKey));
    }
    return headers;
};
const http = async <T>(url: string, options: RequestParams, needToken: boolean, isEncrypt: boolean): Promise<ApiResponse<T>> => {
    const {method = "GET", params = {}, body = {}} = options;
    const responseInterceptor = ({code, msg, data, rows, total, otherInfo}: ApiResponse<T>): ApiResponse<T> => {
        // 获取错误信息
        const message = errorCode[code] || msg || errorCode["default"];
        if (code == HttpStatus.UNAUTHORIZED) {
            // 删除token
            removeToken();
            removeUserInfo();
            showMessage(message, "warning");
            throw new Error(message);
        } else if (code === HttpStatus.SERVER_ERROR) {
            showMessage(message, "warning");
            throw new Error(message);
        } else if (code !== HttpStatus.SUCCESS) {
            showMessage(message, "warning");
            throw new Error(message);
        } else {
            if (rows) {
                return {code, msg, rows, total, otherInfo};
            } else {
                return {code, msg, data};
            }
        }
    };

    const res: any = await $fetch<ApiResponse<T>>(baseUrl + url, {
        headers: requestHeaders(needToken, isEncrypt),
        method,
        params: ["GET", "DELETE"].includes(method.toUpperCase()) ? params : undefined,
        body: ["POST", "PUT"].includes(method.toUpperCase()) ? (isEncrypt ? encryptWithAes(body, aesKey) : body) : undefined,
        onResponseError(err: any) {
            if (err.response.status == HttpStatus.SERVER_ERROR) {
                showMessage("后端接口连接异常", "warning");
                return Promise.reject(err);
            }
            console.log(err);
            console.log("onRequestError", err.response.status);
        },
    });
    return responseInterceptor(res);
};
const get = async <T>(url: string, needToken = false, params = {}): Promise<ApiResponse<T>> => {
    try {
        return await http<T>(url, {method: "GET", params}, needToken, false);
    } catch (error: any) {
        throw error;
    }
};


const del = async <T>(url: string, needToken = false, params = {}): Promise<ApiResponse<T>> => {
    try {
        return await http<T>(url, {method: "DELETE", params}, needToken, false);
    } catch (error: any) {
        throw error;
    }
};

const post = async <T>(url: string, needToken = false, body = {}, isEncrypt = false): Promise<ApiResponse<T>> => {
    try {
        return await http<T>(url, {method: "POST", body}, needToken, isEncrypt);
    } catch (error: any) {
        throw error;
    }
};

const put = async <T>(url: string, needToken = false, body = {}, isEncrypt = false): Promise<ApiResponse<T>> => {
    try {
        return await http<T>(url, {method: "PUT", body}, needToken, isEncrypt);
    } catch (error: any) {
        throw error;
    }
};

export {http, get, del, post, put};
